package br.com.intelsys.basics.utils;

import imageUtil.Image;
import imageUtil.ImageLoader;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class IPicture {
	public static final int IPICTURE_BIGGER_ERROR = -1;
	private static Log log = LogFactory.getLog(IPicture.class);

	class IPictureSize {
		private final int width;
		private final int height;

		IPictureSize(int width, int height) {
			this.width = width;
			this.height = height;
		}

		public int getWidth() {
			return width;
		}

		public int getHeight() {
			return height;
		}

		@Override
		public String toString() {
			return "{" + super.toString() + ": width=" + width + ", height=" + height + "}";
		}
	}

	public void scale(File file, int width, int height) throws IOException {
		if (log.isDebugEnabled()) {
			log.debug("Resize " + file.getName() + " to " + width + " x " + height);
		}
		Image image = ImageLoader.fromFile(file);
		image.getResizedToWidth(width).writeToJPG(file, 1);
	}

	// 180 239 179
	static int calcPropResize(int actualWidth, int actualHeight, int newSize, boolean insertWidthAndReturnHeight) {
		float ratio;
		int retSize;
		if (insertWidthAndReturnHeight) {
			if (actualWidth > newSize) {
				ratio = (float) actualHeight / actualWidth;
				retSize = (int) Math.ceil(newSize * ratio);
				if (retSize > actualHeight) {
					retSize = IPICTURE_BIGGER_ERROR;
				}
			} else {
				retSize = IPICTURE_BIGGER_ERROR;
			}
		} else {
			if (actualHeight > newSize) {
				ratio = (float) actualWidth / actualHeight;
				retSize = (int) Math.ceil(newSize * ratio);
				if (retSize > actualWidth) {
					retSize = IPICTURE_BIGGER_ERROR;
				}
			} else {
				retSize = IPICTURE_BIGGER_ERROR;
			}
		}
		return retSize;
	}

	public static void fitScaleTo(final File file, final int width, final int height) throws IOException {
		IPicture ip = new IPicture();
		IPictureSize size = ip.fitScaleTo(ImageIO.read(file), width, height);
		if (size != null) {
			ip.scale(file, size.getWidth(), size.getHeight());
		}
	}

	IPictureSize fitScaleTo(BufferedImage bsrc, final int width, final int height) throws IOException {
		int actualWidth = bsrc.getWidth();
		int actualHeight = bsrc.getHeight();

		if (actualWidth > width || actualHeight > height) {

			if (actualHeight > actualWidth) {// retrato
				int tmpWidth = calcPropResize(actualWidth, actualHeight, height, false);
				if (tmpWidth == IPICTURE_BIGGER_ERROR) {
					actualHeight = calcPropResize(actualWidth, actualHeight, width, true);
					actualWidth = width;
				} else {
					actualHeight = height;
					actualWidth = tmpWidth;
				}
			} else {// paisagem
				int tmpHeight = calcPropResize(actualWidth, actualHeight, width, true);
				if (tmpHeight == IPICTURE_BIGGER_ERROR) {
					actualWidth = calcPropResize(actualWidth, actualHeight, height, false);
					actualHeight = height;
				} else {
					actualWidth = width;
					actualHeight = tmpHeight;
				}
			}

			if (bsrc.getWidth() != actualWidth || bsrc.getHeight() != actualHeight) {
				return new IPictureSize(actualWidth, actualHeight);
			}
		}
		return null;
	}
}
